package service

import (
	"BlazeRider-backend/app/manager"
	"BlazeRider-backend/app/manager/douyin"
	"BlazeRider-backend/app/models"
	"BlazeRider-backend/app/utils"
	"fmt"
	"sort"
	"time"
)

type DouYinService struct{}

func (ls DouYinService) GetToken() (string, error) {
	tokenInfo, err := manager.Get().DyTokenManager().GetLastCanUseToken()
	if err == nil {
		return tokenInfo.Token, nil
	}

	accessToken, expireIn, err := douyin.GetDouyinToken()
	if err != nil {
		return "", err
	}

	fmt.Println("get dou yin token ", accessToken, expireIn)
	err = manager.Get().DyTokenManager().AddToken(accessToken)
	if err != nil {
		return "", err
	}

	return accessToken, nil
}

func (ls DouYinService) StartDouYinLiveRoomAllTask(liveRoomId string) error {
	token, err := ls.GetToken()
	if err != nil {
		return err
	}

	err = douyin.StartDouYinLiveRoomAllTask(token, liveRoomId)
	if err != nil {
		return err
	}
	return nil
}

func (ls DouYinService) StopDouYinLiveRoomAllTask(liveRoomId string) error {
	token, err := ls.GetToken()
	if err != nil {
		return err
	}

	err = douyin.StopDouYinLiveRoomAllTask(token, liveRoomId)
	if err != nil {
		return err
	}
	return nil
}

func (ls DouYinService) SyncGameStatusToDouYinService(liveRoomId string, status int, FinishTrackInfo []models.FinishTrackInfo) error {
	token, err := ls.GetToken()
	if err != nil {
		return err
	}

	liveRoomInfo, err := manager.Get().LiveRoomManager().GetLiveInfo(liveRoomId)
	loc, _ := time.LoadLocation("Asia/Shanghai")

	startTime := int64(0)
	endTime := int64(0)
	var resultList []models.SyncGameGroupResultToDouYinBody

	if status == 1 {
		startTime = time.Now().In(loc).Unix()
	} else {
		startTime = liveRoomInfo.StartAt.Time.UnixMilli()
		endTime = liveRoomInfo.EndAt.Time.UnixMilli()
		for _, info := range FinishTrackInfo {
			gameResult := 3
			if info.IsChampion == 1 {
				gameResult = 1
			} else if info.IsFinish == 1 {
				gameResult = 2
			} else {
				gameResult = 3
			}
			result := models.SyncGameGroupResultToDouYinBody{
				GroupId: string(info.Track),
				Result:  gameResult,
			}

			resultList = append(resultList, result)
		}
	}

	err = douyin.SyncGameStatusToDouYin(token, liveRoomInfo.AnchorOpenId, liveRoomId, liveRoomInfo.Times, startTime, endTime, status, resultList)
	if err != nil {
		return err
	}
	return nil
}

func (ls DouYinService) SyncUserGroupToDouYinService(liveRoomId string, times int, groupId string, openId string) error {
	token, err := ls.GetToken()
	if err != nil {
		return err
	}

	//liveRoomInfo, err := manager.Get().LiveRoomManager().GetLiveInfo(liveRoomId)

	err = douyin.SyncUserGroupToDouYin(token, liveRoomId, times, groupId, openId)
	if err != nil {
		return err
	}
	return nil
}

func (ls DouYinService) DealUploadUserGameResultService(liveRoomId string) error {
	if liveRoomId == utils.TestRoomId {
		return fmt.Errorf("test room not DealUploadUserGameResultService")
	}
	// 获取直播间信息
	liveRoomInfo, err := manager.Get().LiveRoomManager().GetLiveInfo(liveRoomId)

	token, err := ls.GetToken()
	if err != nil {
		fmt.Println("DealUploadUserGameResultService GetToken err : ", err)
		return err
	}

	//[]models.LiveRoomResult
	liveRoomResult, err := manager.Get().LiveRoomManager().GetLiveRoomResultsForGameRank(liveRoomId, liveRoomInfo.Times)
	if err != nil {
		fmt.Println("DealUploadUserGameResultService GetLiveRoomResults err : ", err)
		return err
	}

	maxTryTimes := 3

	/******* 先处理 上报对局榜单列表 *******/
	var userRankResultList []models.UploadGameRankResultBody

	for _, result := range liveRoomResult {
		gameResult := 2 // 1 胜利， 2 失败 3 平局
		if result.IsFinish == 1 && result.IsChampion == 1 {
			gameResult = 1
		} else if result.IsFinish == 1 && result.IsChampion != 1 {
			gameResult = 3
		}

		userResult := models.UploadGameRankResultBody{
			OpenId:             result.UserID,
			Rank:               result.TotalRank,
			RoundResult:        gameResult,
			Score:              result.TargetScore,
			WinningPoints:      0,
			WinningStreakCount: 0,
		}
		userRankResultList = append(userRankResultList, userResult)
	}
	err = douyin.UploadGameRankResult(token, liveRoomInfo.AnchorOpenId, liveRoomId, liveRoomInfo.Times, userRankResultList)
	if err != nil {
		for tryTimes := 1; tryTimes <= maxTryTimes; tryTimes++ {
			err = douyin.UploadGameRankResult(token, liveRoomInfo.AnchorOpenId, liveRoomId, liveRoomInfo.Times, userRankResultList)
			if err == nil {
				break
			}
		}
	}

	/******* 再处理 上报用户对局数据 *******/
	var userResultList []models.UploadUserGameResultUserBody
	// 创建新切片，长度和容量与原数组相同
	sortResults := make([]models.LiveRoomResult, len(liveRoomResult))
	// 将原数组的内容复制到新切片
	copy(sortResults, liveRoomResult)

	// 按 GetScore 降序排序
	sort.Slice(sortResults, func(i, j int) bool {
		return sortResults[i].GetScore > sortResults[j].GetScore
	})

	for _, result := range liveRoomResult {
		gameResult := 2 // 1 胜利， 2 失败 3 平局
		if result.IsFinish == 1 && result.IsChampion == 1 {
			gameResult = 1
		} else if result.IsFinish == 1 && result.IsChampion != 1 {
			gameResult = 3
		}

		rank := 100

		for i := 0; i < len(sortResults); i++ {
			if sortResults[i].GetScore == result.GetScore {
				rank = i + 1
			}
		}
		userResult := models.UploadUserGameResultUserBody{
			OpenId:             result.UserID,
			Rank:               rank,
			RoundResult:        gameResult,
			Score:              result.TargetScore,
			WinningPoints:      0,
			WinningStreakCount: 0,
		}
		userResultList = append(userResultList, userResult)
	}

	// 计算需要上传的用户 数据批次，单批次最多上报50个用户对局数据
	batchSize := 50
	total := len(userResultList)

	// 遍历所有元素，按批次处理
	for start := 0; start < total; start += batchSize {
		end := start + batchSize
		if end > total {
			end = total // 处理最后不足50个的批次
		}

		// 截取当前批次
		batchUserResultList := userResultList[start:end]

		err = douyin.UploadUserGameResult(token, liveRoomInfo.AnchorOpenId, liveRoomId, liveRoomInfo.Times, batchUserResultList)
		if err != nil {
			for tryTimes := 1; tryTimes <= maxTryTimes; tryTimes++ {
				err = douyin.UploadUserGameResult(token, liveRoomInfo.AnchorOpenId, liveRoomId, liveRoomInfo.Times, batchUserResultList)
				if err == nil {
					break
				}
			}
		}
	}

	/******* 最后处理 完成用户对局数据上报 *******/
	err = douyin.UploadUserGameResultFinish(token, liveRoomInfo.AnchorOpenId, liveRoomId, liveRoomInfo.Times, utils.ConvertNullTimeToTimestamp(liveRoomInfo.EndAt))
	if err != nil {
		for tryTimes := 1; tryTimes <= maxTryTimes; tryTimes++ {
			err = douyin.UploadUserGameResultFinish(token, liveRoomInfo.AnchorOpenId, liveRoomId, liveRoomInfo.Times, utils.ConvertNullTimeToTimestamp(liveRoomInfo.EndAt))
			if err == nil {
				break
			}
		}
	}

	return nil
}

func (ls DouYinService) RequestDouYinForLiveLogin(liveRoomToken string) (models.LiveRoomUserInfo, error) {
	if liveRoomToken == "this@is*Test" {
		return models.LiveRoomUserInfo{
			RoomId:       utils.TestRoomId,
			AnchorOpenId: "testAnchorOpenid",
			AvatarUrl:    "testAvatarUrl",
			NickName:     "TestNickName",
		}, nil
	}

	token, err := ls.GetToken()
	if err != nil {
	}

	roomInfo, err := douyin.GetDouYinRoomInfo(token, liveRoomToken)
	if err != nil {
		fmt.Println("GetDouYinRoomInfo err : ", err)
		return models.LiveRoomUserInfo{
			RoomId:       utils.TestRoomId,
			AnchorOpenId: "testAnchorOpenid",
			AvatarUrl:    "testAvatarUrl",
			NickName:     "TestNickName",
		}, err
	}

	return models.LiveRoomUserInfo{
		RoomId:       roomInfo.RoomId,
		AnchorOpenId: roomInfo.AnchorOpenId,
		AvatarUrl:    roomInfo.AvatarUrl,
		NickName:     roomInfo.NickName,
	}, nil
}

func (ls DouYinService) DealDouYinAllGiftFailedData() error {
	// 先查出来所有正在开始状态的直播间，查询直播间的礼物页数的值，然后查询新的一页
	liveRoomInfoArr, err := manager.Get().LiveRoomManager().GetLiveRoomFailGiftInfoWhenStart()
	if err != nil {

	}

	token, err := ls.GetToken()
	if err != nil {
	}

	for _, info := range liveRoomInfoArr {
		if info.LiveRoomId == utils.TestRoomId {
			continue
		}

		// 获取一下最大的页数
		pageNum := 1
		lastPageInfo, err := manager.Get().DouYinFailGiftRecordManager().GetLastPageNumAndCountByLiveRoomId(info.LiveRoomId)
		if err != nil {
			pageNum = 1
		} else if err == nil {
			pageNum = lastPageInfo.MaxPageNum
			if lastPageInfo.Count == utils.FailGiftRecordPageSize {
				pageNum++
			}
		}

		maxRetries := 5 // 防止死循环

		// 初始化该直播间的数据
		newGiftRecordCount := 0

		for retry := 0; retry < maxRetries; retry++ {
			// 获取下一页数据
			newFailGiftRecodArr, newGiftRecordCount, err := douyin.GetDouYinMissedGiftRecord(
				info.LiveRoomId,
				token,
				pageNum,
				utils.FailGiftRecordPageSize,
			)
			if err != nil {
				fmt.Println("GetDouYinMissedGiftRecord err : ", err)
				break // 或记录日志
			}

			if newFailGiftRecodArr == nil {
				fmt.Println("GetDouYinMissedGiftRecord no record")
				break // 或记录日志
			}

			// 接口频率限制 10次/秒
			time.Sleep(100 * time.Millisecond)

			// 筛选过滤已经记录的
			var msgIds []string
			for _, data := range newFailGiftRecodArr {
				msgIds = append(msgIds, data.MsgID)
			}
			existMsgIds, err := manager.Get().DouYinFailGiftRecordManager().FilterExistingMsgIds(msgIds)

			var recordArr []manager.DouYinFailGiftRecord
			for _, data := range newFailGiftRecodArr {
				if utils.StrExists(existMsgIds, data.MsgID) {
					continue
				}
				record := manager.DouYinFailGiftRecord{
					MsgId:      data.MsgID,
					LiveRoomId: info.LiveRoomId,
					Times:      info.Times,
					UserId:     data.SecOpenID,
					GiftId:     data.SecGiftId,
					Amount:     data.GiftNum,
					Value:      data.GiftValue,
					PageNum:    pageNum,
					TotalValue: data.GiftValue * data.GiftNum,
				}
				recordArr = append(recordArr, record)
			}

			if len(recordArr) == 0 || recordArr == nil {
				pageNum = pageNum + 1
				continue
			}

			// TODO 数据记录db
			err = manager.Get().DouYinFailGiftRecordManager().AddGiftRecordsBatch(recordArr)
			if err != nil {
				fmt.Println("AddGiftRecordsBatch err : ", err)
				break
			}

			// 处理新数据
			for _, giftRecord := range newFailGiftRecodArr {
				if err := manager.Get().UserManager().InitializeUser(
					giftRecord.SecOpenID,
					giftRecord.Nickname,
					giftRecord.AvatarURL,
					1, // 初始等级
				); err != nil {

				}
				err = LiveRoomService{}.OneUserSendGift(giftRecord.MsgID, info.LiveRoomId, giftRecord.SecOpenID, giftRecord.SecGiftId, giftRecord.GiftNum)
				// TODO 标记已经处理的数据
				setStatus := "success"
				reason := ""
				if err != nil {
					fmt.Println("send fail gift record err : ", err)
					setStatus = "fail"
					reason = err.Error()
				}
				err = manager.Get().DouYinFailGiftRecordManager().SetFailGiftDoneOrFail(giftRecord.MsgID, setStatus, reason)
				if err != nil {
					fmt.Println("set fail gift record status err : ", err)
				}
			}

			// 更新终止条件
			if newGiftRecordCount <= pageNum*utils.FailGiftRecordPageSize {
				break
			}

			pageNum++
		}

		pageWholeDeal := 0
		if newGiftRecordCount == pageNum*utils.FailGiftRecordPageSize {
			pageWholeDeal = 1
		}
		manager.Get().LiveRoomManager().SetLiveRoomFailGiftNum(info.LiveRoomId, pageNum, pageWholeDeal)
	}

	return nil
}
